package com.zsrt.devbase.common.shiro;

import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;

import com.zsrt.devbase.common.utils.ConstantDefine;
import com.zsrt.devbase.common.utils.ShiroUtil;
import com.zsrt.devbase.dto.AccountDTO;
import com.zsrt.devbase.service.AccountService;

/**
 * 密码错误锁定，防暴力破解
 * @author leixin
 * @Date 2017年4月26日
 * @version 1.0
 */
public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
	private Cache<String, AtomicInteger> passwordRetryCache;

	@Autowired
	private AccountService accountService;

	/*
	@Autowired
	private LogUserFailDAO logUserFailDAO;
	
	@Autowired
	private AccountInfoDAO accountInfoDAO;*/

	public RetryLimitHashedCredentialsMatcher() {

	}

	public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager) {
		passwordRetryCache = cacheManager.getCache("passwordRetryCache");
	}

	@Override
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		boolean matches = super.doCredentialsMatch(token, info);
		if (matches) {
			//匹配成功，把account信息放入Session;
			AccountDTO accountInfo = (AccountDTO) info.getPrincipals().getPrimaryPrincipal();
			ShiroUtil.setSession(ConstantDefine.ACCOUNT_SESSION, accountInfo);
			
			//把该用户的角色信息放入Session中
			List<String> roleList  = accountService.getRoleListByAccount(accountInfo);
			ShiroUtil.setSession(ConstantDefine.ROLE_SESSION, roleList);
		}
		//String username = (String) token.getPrincipal();
		/*AccountDTO accountPara = new AccountDTO();
		accountPara.setAccountCode(username);
		accountPara.setPersonCode(username);
		AccountDTO account = accountInfoService.getAccountInfo(accountPara);
		String accountStatus = account.getState();
		if ("2".equals(accountStatus)) {// 说明账号目前还处于锁定状态
			LogUserFailDTO logUserFailDTO = new LogUserFailDTO();
			logUserFailDTO.setCreator(username);
			logUserFailDTO.setState("1");
			logUserFailDTO = logUserFailDAO.selectOne(logUserFailDTO);// 获取锁定账户登录尝试的次数
			int failCount = logUserFailDTO.getFailCount();
			int hours = (int) Math.pow(2, failCount - 4);// 计算锁定时间
			// 计算上次最后尝试登陆的时间与现在相隔多少分钟
			int lastTryTime = DateUtil.minutesBetween(account.getModifyTime(), DateUtil.getSystemTimeStr());
			int timeInterval = hours * 60 - lastTryTime;
			if (timeInterval >= 0) {// 还没过锁定时间，禁止登陆
				if (timeInterval > 60) {
					int hour = timeInterval / 60;
					throw new ExcessiveAttemptsException("账号已经锁定,请" + (hour + 1) + "小时后登录");
				} else {
					throw new ExcessiveAttemptsException("账号已经锁定,请" + timeInterval + "分钟后登录");
				}
			} else {//锁定时间已过，进行登录验证
				if (matches) {//登录验证成功,将当前尝试登录的账号设置为解锁，并且删除锁定信息
					// clear retry count
					account.setState("1");
					account.setModifier(username);
					account.setModifyTime(DateUtil.getSystemTimeStr());
					accountInfoDAO.updateByPrimaryKey(account);//设置账号状态
					logUserFailDTO.setState("0");
					logUserFailDTO.setModifier(username);
					logUserFailDTO.setModifyTime(DateUtil.getSystemTimeStr());;
					logUserFailDAO.updateByPrimaryKey(logUserFailDTO);//删除锁定信息
					passwordRetryCache.remove(username);//清除错误舱室缓存
				}else {//验证失败，继续锁定账户，更新account修改时间，并且更新锁定信息
					logUserFailDTO.setFailCount(failCount+1);
					logUserFailDAO.updateByPrimaryKey(logUserFailDTO);
					account.setModifier(username);
					account.setModifyTime(DateUtil.getSystemTimeStr());
					accountInfoDAO.updateByPrimaryKey(account);
					throw new ExcessiveAttemptsException("账号已锁定，请稍后再尝试登录");
				}
			}
		} else {
			if (!matches) {//
				AtomicInteger retryCount = passwordRetryCache.get(username);
				if (retryCount == null) {
					retryCount = new AtomicInteger(0);
					passwordRetryCache.put(username, retryCount);
				} else {
					if (retryCount.incrementAndGet() > 4) {
						// if retry count > 5 throw
						LogUserFailDTO logUserFailDTO = new LogUserFailDTO();
						logUserFailDTO.setCreator(username);
						logUserFailDTO.setCreateTime(DateUtil.getSystemTimeStr());
						logUserFailDTO.setModifier(username);
						logUserFailDTO.setModifyTime(DateUtil.getSystemTimeStr());
						logUserFailDTO.setState("1");
						logUserFailDTO.setFailCount(retryCount.decrementAndGet());
						logUserFailDAO.insert(logUserFailDTO);//插入一条错误尝试记录logUserFailDTO到数据库中
						account.setState("2");
						account.setModifier(username);
						account.setModifyTime(DateUtil.getSystemTimeStr());
						accountInfoDAO.updateByPrimaryKey(account);//将当前尝试登录的账号设置为锁定
						throw new ExcessiveAttemptsException("账号已锁定，请两小时后再尝试登录");
					}
				} 
			}else {
				AtomicInteger retryCount = passwordRetryCache.get(username);
				if (retryCount != null) {
					passwordRetryCache.remove(username);
				}
			}
		}*/
		// retry count + 1
		return matches;

	}
}
